<?php

namespace app\crontab\controller;

use app\common\helpers\Tools;
use ReflectionMethod;

/**
 * 定时任务基类
 */
abstract class BaseCrontab
{

    protected $time;

    public function __construct()
    {
        if (!request()->isCli()) {
            $this->show_msg("请在cli模式下运行");
        }
        $this->_initialize();
    }

    public function _initialize()
    {

    }

    /**
     * 注释包含"<span color='red'>@execute true</span>"并且可见范围为public的方法才会执行定时任务<br>
     * 执行顺序为类代码<span color='blue'>自上到下</span>,如果多个任务需要顺序执行需要合并为一个任务<br>
     * 此方法运行完毕后会结束脚本
     * @return void
     */
    public function index()
    {
        $this->time = time();

        $class          = new \ReflectionClass(static::class);
        $methods        = $class->getMethods(ReflectionMethod::IS_PUBLIC);
        $classStartTime = time();
        foreach ($methods as $method) {
            if (preg_match('/@execute\s+true/ui', $method->getDocComment())) {
                $methodStartTime = time();
                try {
                    $method->invoke($this);
                } catch (\Exception $exception) {
                    //记录异常
                    $this->show_msg($method->getName() . '出现异常:' . $exception->getMessage());
                }
                $methodEndTime = time();
                //记录耗时
                $this->show_msg('方法' . $method->getName() . '耗时:' . ($methodEndTime - $methodStartTime) . '秒');
            }
        }
        $classEndTime = time();
        $this->show_msg('任务' . $class->getShortName() . '总耗时:' . ($classEndTime - $classStartTime) . '秒');
    }

    /**
     * @param      $msg
     * @param bool $trace 记录日志
     */
    protected function show_msg($msg, bool $trace = false)
    {
        if (is_array($msg)) {
            $msg = json_encode($msg, JSON_UNESCAPED_UNICODE);
        }
        Tools::show_msg($msg);
        ($trace) && trace($msg, 'every_day');
    }

}